using System.Diagnostics;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Media;
using Avalonia.Styling;
using Avalonia.Threading;
using Avalonia.VisualTree;

// Needed for TemplateAppliedEventArgs if you keep using it
// Needed for IDataTemplate if you manually add ContentTemplate

// Required for Visual, HorizontalAlignment, VerticalAlignment


namespace AvaloniaUiKit.Controls;// Replace with your actual namespace

// Inherit from ContentControl instead of TemplatedControl
public class AnimatedCard : ContentControl // <--- CHANGE HERE
{
    // No need to define ContentProperty, ContentTemplateProperty,
    // HorizontalContentAlignmentProperty, VerticalContentAlignmentProperty, or PaddingProperty manually.
    // They are inherited from ContentControl.

    private Border? _mainBorder;
    private Animation? _borderAnimation;
    private bool _isAnimating = false;

    // --- Dependency Properties (Specific to AnimatedCard) ---

    public static readonly StyledProperty<IBrush> CardBackgroundProperty =
        AvaloniaProperty.Register<AnimatedCard, IBrush>(
            nameof(CardBackground),
            defaultValue: SolidColorBrush.Parse("#191c29")); // <-- 直接提供默认值

    public IBrush CardBackground
    {
        get => GetValue(CardBackgroundProperty);
        set => SetValue(CardBackgroundProperty, value);
    }

    public static readonly StyledProperty<LinearGradientBrush> GlowBrushProperty =
        AvaloniaProperty.Register<AnimatedCard, LinearGradientBrush>(
            nameof(GlowBrush),
            defaultValue: CreateDefaultGlowBrush()); // <-- 直接提供默认值

    public LinearGradientBrush GlowBrush
    {
        get => GetValue(GlowBrushProperty);
        set => SetValue(GlowBrushProperty, value);
    }

    public static readonly StyledProperty<Thickness> CardBorderThicknessProperty =
        AvaloniaProperty.Register<AnimatedCard, Thickness>(nameof(CardBorderThickness), new Thickness(3));

    public Thickness CardBorderThickness
    {
        get => GetValue(CardBorderThicknessProperty);
        set => SetValue(CardBorderThicknessProperty, value);
    }

    public static readonly StyledProperty<CornerRadius> CardCornerRadiusProperty =
        AvaloniaProperty.Register<AnimatedCard, CornerRadius>(nameof(CardCornerRadius), new CornerRadius(10));

    public CornerRadius CardCornerRadius
    {
        get => GetValue(CardCornerRadiusProperty);
        set => SetValue(CardCornerRadiusProperty, value);
    }

    public static readonly StyledProperty<double> GlowBlurRadiusProperty =
        AvaloniaProperty.Register<AnimatedCard, double>(nameof(GlowBlurRadius), 21.0);

    public double GlowBlurRadius
    {
        get => GetValue(GlowBlurRadiusProperty);
        set => SetValue(GlowBlurRadiusProperty, value);
    }

    public static readonly StyledProperty<Vector> GlowScaleProperty =
        AvaloniaProperty.Register<AnimatedCard, Vector>(nameof(GlowScale), new Vector(1, 1));

    public Vector GlowScale
    {
        get => GetValue(GlowScaleProperty);
        set => SetValue(GlowScaleProperty, value);
    }

    public static readonly StyledProperty<Point> GlowOffsetProperty =
        AvaloniaProperty.Register<AnimatedCard, Point>(nameof(GlowOffset), new Point(0, 0));

    public Point GlowOffset
    {
        get => GetValue(GlowOffsetProperty);
        set => SetValue(GlowOffsetProperty, value);
    }

    public static readonly StyledProperty<TimeSpan> AnimationDurationProperty =
        AvaloniaProperty.Register<AnimatedCard, TimeSpan>(nameof(AnimationDuration), TimeSpan.FromSeconds(2));

    public TimeSpan AnimationDuration
    {
        get => GetValue(AnimationDurationProperty);
        set => SetValue(AnimationDurationProperty, value);
    }

    // --- Internal Property to Drive Animation ---
    private static readonly DirectProperty<AnimatedCard, double> RotateAngleProperty =
       AvaloniaProperty.RegisterDirect<AnimatedCard, double>(
           nameof(RotateAngle),
           o => o.RotateAngle,
           (o, v) => o.RotateAngle = v);

    private double _rotateAngle = 0;
    private double RotateAngle
    {
        get => _rotateAngle;
        set
        {
            if (SetAndRaise(RotateAngleProperty, ref _rotateAngle, value))
            {
                // Defer update slightly to avoid issues during layout/animation cycles
                Dispatcher.UIThread.Post(() => UpdateGradientRotation(value), DispatcherPriority.Render);
            }
        }
    }

    // --- Constructor & Overrides ---

    static AnimatedCard()
    {
        // Set default values using OverrideMetadata or OverrideDefaultValue
        //GlowBrushProperty.OverrideDefaultValue<AnimatedCard>(CreateDefaultGlowBrush());
        //CardBackgroundProperty.OverrideDefaultValue<AnimatedCard>(SolidColorBrush.Parse("#191c29"));

        // ContentControl handles metadata for Content, Padding, Alignment properties.
        // We only need to register metadata for *our* custom properties.
        AffectsRender<AnimatedCard>(
            CardBackgroundProperty,
            GlowBrushProperty,
            CardBorderThicknessProperty,
            CardCornerRadiusProperty,
            GlowBlurRadiusProperty,
            GlowScaleProperty,
            GlowOffsetProperty);
        AffectsMeasure<AnimatedCard>(CardBorderThicknessProperty);
        AffectsArrange<AnimatedCard>(); // Base ContentControl affects arrange

        // Optional: AnimationDuration could affect render indirectly if animation changes visual props
        // AffectsRender<AnimatedCard>(AnimationDurationProperty);
    }

    // Constructor remains the same
    public AnimatedCard() { }

    protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
    {
        base.OnApplyTemplate(e); // Call base for ContentControl logic
        _mainBorder = e.NameScope.Find<Border>("PART_MainBorder");

        StopAnimation(); // Stop previous if template reapplies

        if (_mainBorder != null)
        {
            // Apply initial rotation state
            UpdateGradientRotation(RotateAngle);
            // Start animation (deferred)
            Dispatcher.UIThread.Post(StartAnimation, DispatcherPriority.Background);
        }
        else
        {
            Debug.WriteLine("[AnimatedCard] PART_MainBorder not found in template.");
        }
    }

    // OnAttachedToVisualTree/OnDetachedFromVisualTree remain the same

    protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
    {
        base.OnAttachedToVisualTree(e);
        if (_mainBorder != null && !_isAnimating)
        {
            Dispatcher.UIThread.Post(StartAnimation, DispatcherPriority.Background);
        }
    }

    protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
    {
        StopAnimation();
        base.OnDetachedFromVisualTree(e);
    }


    // --- Animation Logic --- (Remains the same)
    private void StartAnimation()
    {
        if (_mainBorder == null || _isAnimating || !this.IsAttachedToVisualTree()) return;


        _borderAnimation = new Animation
        {
            Duration = GetValue(AnimationDurationProperty),
            IterationCount = IterationCount.Infinite,
            Easing = new LinearEasing(),
            Children =
            {
                new KeyFrame { Cue = new Cue(0), Setters = { new Setter(RotateAngleProperty, 0.0) } },
                new KeyFrame { Cue = new Cue(1), Setters = { new Setter(RotateAngleProperty, Math.PI * 2) } }
            }
        };

        // It's generally recommended to provide a CancellationTokenSource
        // if you need fine-grained control over stopping the animation,
        // but for infinite animations tied to control lifetime, null clock is often sufficient.

        _borderAnimation.RunAsync(this, CancellationToken.None);
        _isAnimating = true;
        Debug.WriteLine("[AnimatedCard] Animation Started.");
    }

    private void StopAnimation()
    {
        // Rely on detaching from visual tree to stop the animation implicitly
        _isAnimating = false;
        Debug.WriteLine("[AnimatedCard] Animation Stopped (or control detached).");
    }

    // --- Gradient Rotation Logic --- (Remains the same)
    private void UpdateGradientRotation(double rotation)
    {
        if (_mainBorder == null || !this.IsArrangeValid) return; // Don't update if layout isn't valid

        var linearGradientBrush = GetValue(GlowBrushProperty);
        if (linearGradientBrush == null) return;

        var borderRect = new Rect(_mainBorder.Bounds.Size);
        if (borderRect.Width <= 0 || borderRect.Height <= 0)
        {
            // Don't log excessively, maybe only once or when size changes to zero
            // Debug.WriteLine("[AnimatedCard] Warning: MainBorder size is zero, cannot calculate gradient rotation.");
            return;
        }

        SetGradientRotation(borderRect, linearGradientBrush, rotation);
    }

    // SetGradientRotation static method remains the same
    private static void SetGradientRotation(Rect borderRect, LinearGradientBrush linearGradientBrush, double rotation)
    {
        // ... (gradient calculation logic as before) ...
        // Normalize rotation to be between 0 and 2*PI
        rotation = rotation % (2 * Math.PI);
        if (rotation < 0) rotation += (2 * Math.PI);

        // Calculate tangent, handle vertical cases carefully
        double m = (Math.Abs(rotation - Math.PI / 2.0) < 1e-5 || Math.Abs(rotation - 3.0 * Math.PI / 2.0) < 1e-5)
                   ? double.PositiveInfinity // Vertical line
                   : Math.Tan(rotation);

        Point GetIntersection(bool followDirection)
        {
            double currentRotation = followDirection ? rotation : (rotation + Math.PI) % (2 * Math.PI);
            double centerX = borderRect.Width / 2.0;
            double centerY = borderRect.Height / 2.0;

            // Handle cardinal directions first for precision and simplicity
            if (Math.Abs(currentRotation) < 1e-5 || Math.Abs(currentRotation - 2 * Math.PI) < 1e-5) // 0 degrees (Right)
                return new Point(borderRect.Width, centerY);
            if (Math.Abs(currentRotation - Math.PI / 2.0) < 1e-5) // 90 degrees (Bottom)
                return new Point(centerX, borderRect.Height);
            if (Math.Abs(currentRotation - Math.PI) < 1e-5) // 180 degrees (Left)
                return new Point(0, centerY);
            if (Math.Abs(currentRotation - 3.0 * Math.PI / 2.0) < 1e-5) // 270 degrees (Top)
                return new Point(centerX, 0);

            // General case using line equation: y - cy = m * (x - cx)
            // Need to handle infinite slope (vertical lines)
            double yAtRight = double.IsInfinity(m) ? (currentRotation == Math.PI / 2.0 ? borderRect.Height : 0) : m * (borderRect.Width - centerX) + centerY;
            double yAtLeft = double.IsInfinity(m) ? (currentRotation == Math.PI / 2.0 ? borderRect.Height : 0) : m * (0 - centerX) + centerY;
            double xAtBottom = double.IsInfinity(m) ? centerX : (borderRect.Height - centerY) / m + centerX;
            double xAtTop = double.IsInfinity(m) ? centerX : (0 - centerY) / m + centerX;


            // Determine which edge is intersected based on the quadrant of the rotation
            if (currentRotation > 0 && currentRotation < Math.PI / 2.0) // Quadrant 1 (Bottom or Right)
            {
                if (double.IsInfinity(m)) return new Point(centerX, borderRect.Height); // Vertical line going down
                if (yAtRight <= borderRect.Height + 1e-5) return new Point(borderRect.Width, Math.Max(0, yAtRight)); // Intersects right edge (clamp Y)
                else return new Point(Math.Clamp(xAtBottom, 0, borderRect.Width), borderRect.Height); // Intersects bottom edge (clamp X)
            }
            else if (currentRotation > Math.PI / 2.0 && currentRotation < Math.PI) // Quadrant 2 (Bottom or Left)
            {
                if (double.IsInfinity(m)) return new Point(centerX, borderRect.Height); // Vertical line going down (shouldn't happen here)
                if (yAtLeft <= borderRect.Height + 1e-5) return new Point(0, Math.Max(0, yAtLeft)); // Intersects left edge (clamp Y)
                else return new Point(Math.Clamp(xAtBottom, 0, borderRect.Width), borderRect.Height); // Intersects bottom edge (clamp X)
            }
            else if (currentRotation > Math.PI && currentRotation < 3.0 * Math.PI / 2.0) // Quadrant 3 (Top or Left)
            {
                if (double.IsInfinity(m)) return new Point(centerX, 0); // Vertical line going up
                if (yAtLeft >= -1e-5) return new Point(0, Math.Min(borderRect.Height, yAtLeft)); // Intersects left edge (clamp Y)
                else return new Point(Math.Clamp(xAtTop, 0, borderRect.Width), 0); // Intersects top edge (clamp X)
            }
            else // Quadrant 4 (Top or Right)
            {
                if (double.IsInfinity(m)) return new Point(centerX, 0); // Vertical line going up (shouldn't happen here)
                if (yAtRight >= -1e-5) return new Point(borderRect.Width, Math.Min(borderRect.Height, yAtRight)); // Intersects right edge (clamp Y)
                else return new Point(Math.Clamp(xAtTop, 0, borderRect.Width), 0); // Intersects top edge (clamp X)
            }
        }

        Point startPointAbs = GetIntersection(false); // Point opposite to rotation direction
        Point endPointAbs = GetIntersection(true);   // Point in rotation direction

        // Convert absolute intersection points to relative points (0 to 1)
        var startPointRel = new RelativePoint(startPointAbs.X / borderRect.Width, startPointAbs.Y / borderRect.Height, RelativeUnit.Relative);
        var endPointRel = new RelativePoint(endPointAbs.X / borderRect.Width, endPointAbs.Y / borderRect.Height, RelativeUnit.Relative);

        // Check if points are effectively the same (can happen with small rects or precision issues)
        if (Math.Abs(startPointRel.Point.X - endPointRel.Point.X) < 1e-6 && Math.Abs(startPointRel.Point.Y - endPointRel.Point.Y) < 1e-6)
        {
            // Fallback for very small sizes or degenerate cases, e.g., 0-180 degree gradient
            // Choose a diagonal that's likely different from the intended rotation
            if (Math.Abs(rotation - Math.PI) < 1e-5 || Math.Abs(rotation) < 1e-5) // near 0 or 180
            {
                startPointRel = new RelativePoint(0.5, 0, RelativeUnit.Relative); // Top-center
                endPointRel = new RelativePoint(0.5, 1, RelativeUnit.Relative);   // Bottom-center
            }
            else
            { // near 90 or 270
                startPointRel = new RelativePoint(0, 0.5, RelativeUnit.Relative); // Left-center
                endPointRel = new RelativePoint(1, 0.5, RelativeUnit.Relative);   // Right-center
            }
            Debug.WriteLine($"[AnimatedCard] Degenerate gradient points for rotation {rotation}, using fallback.");
        }


        linearGradientBrush.StartPoint = startPointRel;
        linearGradientBrush.EndPoint = endPointRel;
    }

    // Helper to create the default gradient brush instance
    private static LinearGradientBrush CreateDefaultGlowBrush()
    {
        // Use Color.Parse for simplicity, assuming standard hex format
        return new LinearGradientBrush
        {
            StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), // Initial state, will be updated
            EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative),   // Initial state, will be updated
            GradientStops = new GradientStops
            {
                new GradientStop(Color.Parse("#5ddcff"), 0),
                new GradientStop(Color.Parse("#3c67e3"), 0.43),
                new GradientStop(Color.Parse("#4e00c2"), 1)
            }
        };
    }
}